/*
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  Author: hakanai
  Email:  hakanai at dnmx.0rg
*/

#include <avr/io.h>
#include <stdio.h>
#include "uart.h"

#define UART_BAUD_SELECT(baudRate,xtalCpu) (((xtalCpu)+8UL*(baudRate))/(16UL*(baudRate))-1UL)

/*
 * It is xxxx 8 N 1 initialization
 * xxxx - means boudrate which is the only option
 * 9600 8N1 works just fine
 */
void uart_init(int baud) {
  UBRR = (uint8_t)UART_BAUD_SELECT(baud, F_CPU);

  /*
   * The RXB8 could be skiped because it's RO nature,
   * so lets keep it simple.
   */
  UCR = _BV(TXB8)|_BV(RXEN)|_BV(TXEN);
  /*
   * TODO:
   * Check if this is a neceserry bit set
   * when uart_getchar() goes first on a first run.
   */
  USR = _BV(TXC);
}

/*
 * There is a problem with the TXC bit
 * which is a R/W bit of the USR. A problem is
 * status of the bit which does not reset properly.
 * Therefore I've decided to set it manually and wait for
 * its reset for an every transission.
 */
void uart_putchar(char c) {
  USR = _BV(TXC);
  UDR = c;
  loop_until_bit_is_set(USR, TXC);
}

int uart_getchar() {
  loop_until_bit_is_set(USR, RXC);
  return UDR;
}
